package com.blue.http.invoke;

import java.util.List;

import javax.validation.ValidationException;

import com.blue.http.message.View;
import org.springframework.beans.BeansException;

import com.alibaba.fastjson.JSONException;
import com.blue.core.util.JsonUtil;
import com.blue.http.annotation.HttpFilterParser;
import com.blue.http.annotation.HttpParser;
import com.blue.http.config.ErrorConfig;
import com.blue.http.message.DefaultHttpResponse;
import com.blue.http.message.HttpRequest;
import com.blue.http.message.HttpResponse;
import com.blue.http.util.HttpException;
import com.blue.http.util.HttpLogUtil;

/**
 * HTTP调用
 * 
 * @author zhengj
 * @since 1.0 2017年3月14日
 */
public class Invoker
{
	private final HttpParser httpParser;
	private final HttpFilterParser httpFilterParser;
	private ErrorConfig errorConfig = ErrorConfig.getInstance();
	
	public Invoker(HttpParser httpParser, HttpFilterParser httpFilterParser)
	{
		this.httpParser = httpParser;
		this.httpFilterParser = httpFilterParser;
	}
	
	/**
	 * 方法调用
	 * 
	 * @param request 参数
	 */
	public HttpResponse invoke(HttpRequest request)
	{
		HttpResponse response = new DefaultHttpResponse();
		try
		{
			this.preHandler(request, response);
			
			Object obj = httpParser.invoke(request);
			if (obj != null)
			{
				if (obj instanceof CharSequence)
				{
					response.setResult(obj.toString());
				}
				else if (obj instanceof View)
				{
					View v = (View)obj;
					response.setLocation(v.getLocation());
				}
				else
				{
					response.setResult(JsonUtil.output(obj));
				}
			}
			if (response.isLocation())
			{
				HttpLogUtil.log(request, "跳转：" + response.getLocation());
			}
			else
			{
				HttpLogUtil.log(request, response.getResult());
			}
			
			this.afterHandler(request, response);
		}
		catch (ValidationException e)
		{
			response.setCode(ErrorConfig.PARAM);
			response.setMsg(errorConfig.get(ErrorConfig.PARAM));
			response.setExtmsg(e.getMessage());
			HttpLogUtil.log(request, response, e);
		}
		catch (BeansException e)
		{
			response.setCode(ErrorConfig.NOT_FOUND);
			response.setMsg(errorConfig.get(ErrorConfig.NOT_FOUND));
			HttpLogUtil.log(request, response, e);
		}
		catch (JSONException e)
		{
			response.setCode(ErrorConfig.JSON);
			response.setMsg(errorConfig.get(ErrorConfig.JSON));
			HttpLogUtil.log(request, response, e);
		}
		catch (HttpException e)
		{
			response.setCode(e.getCode());
			response.setMsg(e.getMessage());
			HttpLogUtil.log(request, response, e);
		}
		catch (Exception e)
		{
			response.setCode(ErrorConfig.ERROR);
			response.setMsg(errorConfig.get(ErrorConfig.ERROR));
			HttpLogUtil.log(request, response, e);
		}
		
		return response;
	}
	
	private void preHandler(HttpRequest request, HttpResponse response) throws Exception
	{
		List<InvokerFilter> filterList = httpFilterParser.allFilter();
		if (filterList == null || filterList.isEmpty())
			return;
		
		String url = request.getUrl();
		for (InvokerFilter filter : filterList)
		{
			if (!httpFilterParser.match(filter.getClass(), url))
				continue;
			
			boolean result = filter.preHandle(request, response);
			if (!result)
				return;
		}
	}
	
	private void afterHandler(HttpRequest request, HttpResponse response) throws Exception
	{
		List<InvokerFilter> filterList = httpFilterParser.allFilter();
		if (filterList == null || filterList.isEmpty())
			return;
		
		for (int i = filterList.size() - 1; i >= 0; i--)
		{
			InvokerFilter filter = filterList.get(i);
			filter.afterHandle(request, response);
		}
	}
	
	
}
